package top.glike.ssl.auto;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.cas20200407.AsyncClient;
import com.aliyun.sdk.service.cas20200407.models.CreateCertificateRequestRequest;
import com.aliyun.sdk.service.cas20200407.models.ListUserCertificateOrderRequest;
import com.aliyun.sdk.service.cas20200407.models.ListUserCertificateOrderResponse;
import com.aliyun.sdk.service.cas20200407.models.ListUserCertificateOrderResponseBody;
import com.google.gson.Gson;
import darabonba.core.client.ClientOverrideConfiguration;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.glike.ssl.auto.config.SSLConfig;
import top.glike.ssl.auto.domain.other.CertInfo;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * SSL证书自动管理工具
 * 功能：
 * 1. 监控SSL证书到期情况
 * 2. 自动申请即将到期的证书
 * 3. 自动下载nginx格式的证书文件
 */
public class TestMain {

    private static final Logger logger = LoggerFactory.getLogger(TestMain.class);
    private static final String DEFAULT_CONFIG_FILE = "ssl-config.json";

    public static void main(String[] args) {
        try {
            logger.info("=== SSL证书自动管理工具启动 ===");

            // 解析命令行参数
            String configFile = parseConfigFile(args);
            String action = parseAction(args);

            // 检查配置文件
            if (!FileUtil.exist(configFile)) {
                logger.info("配置文件不存在，生成默认配置文件: {}", configFile);
                SSLConfig.generateDefaultConfig(configFile);
                logger.info("请编辑配置文件后重新运行程序");
                return;
            }

            // 加载配置
            SSLConfig config = SSLConfig.loadFromFile(configFile);
            logger.info("配置文件加载成功: {}", configFile);
            logger.info("配置文件加载成功: {}", config);

            // 创建SSL证书服务
            StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                    // Please ensure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set.
                    .accessKeyId(config.getAccessKeyId())
                    .accessKeySecret(config.getAccessKeySecret())
                    //.securityToken(System.getenv("ALIBABA_CLOUD_SECURITY_TOKEN")) // use STS token
                    .build());

            // 获取所有证书
            List<CertInfo> certList = queryCertList(provider);

            // 根据动作执行相应功能
            /*switch (action.toLowerCase()) {
                case "check":
                    checkCertificates(sslService);
                    break;
                case "check-expired":
                    checkExpiredCertificates(sslService);
                    break;
                case "check-all":
                    checkAllCertificatesStatus(sslService);
                    break;
                case "auto":
                    autoRenewCertificates(sslService);
                    break;
                case "list":
                    listAllCertificates(sslService);
                    break;
                case "help":
                    printHelp();
                    break;
                case "down":
                    downloadCertificate(sslService);
                    break;
                default:
                    logger.info("未指定操作，执行默认的证书检查和自动续期");
                    autoRenewCertificates(sslService);
                    break;
            }*/

            logger.info("=== SSL证书管理工具执行完成 ===");

        } catch (Exception e) {
            logger.error("程序执行失败: " + e.getMessage(), e);
            System.exit(1);
        }
    }


    /**
     * 查询证书列表
     *
     * @param provider 配置信息
     */
    public static List<CertInfo> queryCertList(StaticCredentialProvider provider) {
        try {
            // Configure the Client
            AsyncClient client = AsyncClient.builder()
                    .region("cn-hangzhou") // Region ID
                    //.httpClient(httpClient) // Use the configured HttpClient, otherwise use the default HttpClient (Apache HttpClient)
                    .credentialsProvider(provider)
                    //.serviceConfiguration(Configuration.create()) // Service-level configuration
                    // Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.
                    .overrideConfiguration(
                            ClientOverrideConfiguration.create()
                                    // Endpoint 请参考 https://api.aliyun.com/product/cas
                                    .setEndpointOverride("cas.aliyuncs.com")
                            //.setConnectTimeout(Duration.ofSeconds(30))
                    )
                    .build();

            // Parameter settings for API request
            ListUserCertificateOrderRequest listUserCertificateOrderRequest = ListUserCertificateOrderRequest.builder()
                    // Request-level configuration rewrite, can set Http request parameters, etc.
                    // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                    .build();

            // Asynchronously get the return value of the API request
            CompletableFuture<ListUserCertificateOrderResponse> response = client.listUserCertificateOrder(listUserCertificateOrderRequest);
            // Synchronously get the return value of the API request
            ListUserCertificateOrderResponse resp = response.get();
            String json = new Gson().toJson(resp);
            logger.info(json);
            ListUserCertificateOrderResponseBody body = resp.getBody();
            List<ListUserCertificateOrderResponseBody.CertificateOrderList> list = body.getCertificateOrderList();
            logger.info("-----查询证书列表数据-----");
            List<CertInfo> certList = new ArrayList<>();
            for (ListUserCertificateOrderResponseBody.CertificateOrderList info : list) {
                CertInfo certInfo = new CertInfo();
                certInfo.setDomain(info.getDomain());
                certInfo.setStatus(info.getStatus());
                certInfo.setAlgorithm(info.getAlgorithm());
                certInfo.setOrderId(info.getOrderId());
                certInfo.setProductName(info.getProductName());
                certInfo.setCertEndTime(new Date(info.getCertEndTime()));
                certInfo.setCertStartTime(new Date(info.getCertStartTime()));
                certList.add(certInfo);
                Date endDate = new Date(info.getCertEndTime());
                String endTime = DateUtil.format(endDate, "yyyy-MM-dd HH:mm:ss");
                Boolean isExpired = certInfo.isExpired();
                // logger.info("{} - {} - {} - {} - {} - {}", info.getDomain(), info.getStatus(), info.getOrderId(), endTime, info.getCertEndTime(), isExpired);
                logger.info(certInfo.toString());
            }


            CreateCertificateRequestRequest createCertificateRequestRequest = CreateCertificateRequestRequest.builder()
                    .productCode("digicert-free-1-free")
                    .username("Tom")
                    .phone("1390000****")
                    .email("username@example.com")
                    .domain("buss.glike.top")
                    .validateType("DNS")
                    // Request-level configuration rewrite, can set Http request parameters, etc.
                    // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                    .build();


            // Finally, close the client
            client.close();
            return certList;
        } catch (Exception e) {
            logger.error("查询并证书列表出现异常：{}", e.getMessage());
            logger.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析配置文件路径
     */
    private static String parseConfigFile(String[] args) {
        for (int i = 0; i < args.length - 1; i++) {
            if ("-c".equals(args[i]) || "--config".equals(args[i])) {
                return args[i + 1];
            }
        }
        return DEFAULT_CONFIG_FILE;
    }

    /**
     * 解析操作类型
     */
    private static String parseAction(String[] args) {
        for (int i = 0; i < args.length - 1; i++) {
            if ("-a".equals(args[i]) || "--action".equals(args[i])) {
                return args[i + 1];
            }
        }

        // 检查是否有直接的操作参数
        for (String arg : args) {
            if (arg.equals("check") || arg.equals("check-expired") || arg.equals("check-all") ||
                    arg.equals("auto") || arg.equals("list") || arg.equals("help") || arg.equals("down")) {
                return arg;
            }
        }

        return "auto";
    }

    /**
     */
    /**
     * 检查证书到期情况（仅即将到期）
     *
     * @param certList 证书列表
     * @param status   状态 ("":全部; domain_verify:待验证; process:审核中; verify_fail:审核失败; certificate:已签发; payed:待申请; unknow:状态未知)
     */
    private static void checkCertificates(List<CertInfo> certList, String status) {
        logger.info("开始检查{}状态的证书...", status);

        List<CertInfo> list = certList.stream().filter(cert -> StringUtils.equals(status.toUpperCase(), cert.getStatus().toUpperCase())).collect(Collectors.toList());

        if (CollUtil.isEmpty(list) || StringUtils.isNotBlank(status)) {
            logger.info("没有发现{}的证书", status);
        } else {
            logger.warn("发现{}个{}的证书:", list.size(), status);
            for (CertInfo cert : list) {
                logger.info("  - {}", cert);
            }
        }
    }

}